package net.oov.identify;
/**
 * Trie tree
 */
import java.util.HashMap;
import java.util.Map;

import net.oov.identify.model.StatusNode;


public class StatusTree {

	private TreeNode rootNode;
	
	public StatusTree() {
		super();
	}
	
	public TreeNode addNodes(char[] cs) {
		
		return this.addNodes(cs, Boolean.FALSE);
		
	}
	
	public TreeNode addNodes(char[] cs, Boolean isNature) {
		if(cs == null || cs.length==0)return null;
		if(rootNode==null)rootNode = new TreeNode(cs[0],0);
		return rootNode.addNodes(cs, isNature);
	}
	
	public TreeNode rootNode(){
		return this.rootNode;
	}
	
	public void setRootNode(TreeNode tn){
		this.rootNode = tn;
	}
	
	/**
	 * 
	 * @author huangsui.cn
	 *
	 */
	public static class TreeNode implements StatusNode {
		
		private Character key;//key of this node
		private Integer offset;//the offset of char in the string, also the depth of this node
		private Boolean isLeaf = Boolean.TRUE;//leaf of the tree
		private Integer subNodesdepth;// is leaf if the value is 0
		private Map<Character, TreeNode> subNodes;
		
		private Boolean isEndpoint = Boolean.FALSE;//end of string
		private Status status;
		
		public TreeNode(Character key,Integer offset) {
			
			super();
			this.key = key;
			this.offset = offset;
			this.isLeaf = Boolean.TRUE;
			this.subNodesdepth = 0;
			
		}
		
		public TreeNode(Character key,Integer offset,Boolean isLeaf) {
			
			super();
			this.key = key;
			this.offset = offset;
			this.isLeaf = isLeaf;
			this.subNodesdepth = 0;
			
		}
		
		public TreeNode addNodes(char[] cs, Boolean isNature) {
			TreeNode endNode = this.addNodes(cs);
			if(isNature)endNode.freqNatureIncrease();
			return endNode;
		}
		
		
		public TreeNode addNodes(char[] cs) {
			
			if(offset+1==cs.length){//current node is the end of string
				isEndpoint = Boolean.TRUE;
				if(status==null)status = new Status();
				status.freq++;
				return this;
			}
			if(offset+subNodesdepth < cs.length-1){//subNodesDepth
				subNodesdepth = (cs.length-1)-offset;
			}
			Integer nextOffset = this.offset+1;
			TreeNode subNode = this.subNode(cs[nextOffset]);
			if(subNode == null){//no find the subNode,then initialize it and modify some info of current node 
				subNode = new TreeNode(cs[nextOffset],Integer.valueOf(nextOffset));
				if(subNodes == null)subNodes = new HashMap<Character, TreeNode>();
				subNodes.put(cs[nextOffset], subNode);//put it into the sub nodes
				if(this.isLeaf)this.isLeaf = Boolean.FALSE;//current node was a leaf
			}
			return subNode.addNodes(cs);
			
		}
		
		public Integer freq(){
			if(status == null)return 0;
			return status.freq;
		}
		public Integer freqWhole(){
			if(status == null)return 0;
			return status.freqWhole;
		}
		public void freqIncrease(){
			status.freq++;
		}
		
		public void freqNatureIncrease(){
			status.freqWhole++;
		}
		
		public void born(char k, TreeNode sub) {
			subNodes.put(k, sub);
		}
		
		public TreeNode subNode(char k) {
			if(subNodes == null){
				return null;
			}else{
				return subNodes.get(k);
			}
		}
		public boolean isLeaf() {
			return isLeaf;
		}
		public Boolean isEndpoint(){
			return isEndpoint;
		}
		public Character getKey(){
			return key;
		}
		public Integer getOffset(){
			return offset;
		}
		public Map<Character, TreeNode> subNodes(){
			return subNodes;
		}
		
		public String toString(){
			return "endpoint:"+isEndpoint+",leaf:"+isLeaf+","+status.toString();
		}
	}
	
	/**
	 * 
	 * @author huangsui.cn
	 *
	 */
	public static class Status{
		int freq = 0;
		int freqWhole = 0;
		Double conf;
		Double mi;
		Boolean isWord = Boolean.FALSE;
		
		public String toString(){
			return "F:"+freq+",FW:"+freqWhole;
		}
	}
	
}
